FUNCTION_BLOCK LCB_8400Drive8Word
TITLE = 'LCB_8400Drive8W'


// This FB read and write 8 Words of processdata from a connected 8400 Lenze Drive
// The implementation is independant of the used bussystem (Profinet / Profibus)
//
// Used S7 Systemfunctions 
// SFC14 (DPRD_DAT)
// SFC15 (DPWR_DAT)

//
// Versionshistory:
// 1.0 Ersterstellung E.Dittmann


AUTHOR : 'Lenze'
Family : 'LCB'
Version : '1.0'
Name: '84Drv8W'
KNOW_HOW_PROTECT


CONST
    Range := 8; // Count of wors from / to the drive 
END_CONST

VAR_INPUT
    iFirstPeripherieADR         :INT;                               // Peripheral adress of the drive (Hardwareconfig S7)
    xEnableInternalControl      :BOOL:=0;                           // Enable internal drivecontrol with variabletable
    wCtrl                       :WORD:=0;                           // Controlword
    iIn2                        :INT:=0;                            // Processdataword 2 to drive
    iIn3                        :INT:=0;                            // Processdataword 3 to drive
    iIn4                        :INT:=0;                            // Processdataword 4 to drive
    iIn5                        :INT:=0;                            // Processdataword 5 to drive
    iIn6                        :INT:=0;                            // Processdataword 6 to drive
    iIn7                        :INT:=0;                            // Processdataword 7 to drive
    iIn8                        :INT:=0;                            // Processdataword 8 to drive

END_VAR

VAR_OUTPUT
    xError                      :BOOL;                               // Error
    iReadError                  :INT;                                // Errorcode SFC14 
    iWriteError                 :INT;                                // Errorcode SFC15  
    xInternalControlActive      :BOOL;                               // Internal control active
    xCommunicationOK            :BOOL;                               // Communication OK
    wState                      :WORD;                               // Statusword
    iOut2                       :INT;                                // Processdataword 2 from drive
    iOut3                       :INT;                                // Processdataword 3 from drive
    iOut4                       :INT;                                // Processdataword 4 from drive
    iOut5                       :INT;                                // Processdataword 5 from drive
    iOut6                       :INT;                                // Processdataword 6 from drive
    iOut7                       :INT;                                // Processdataword 7 from drive
    iOut8                       :INT;                                // Processdataword 8 from drive

END_VAR

VAR_IN_OUT

END_VAR


VAR
    wFirstPeripherieADR         :WORD;                               
//    awSend                      :ARRAY[1..Range] OF WORD;                         
//    awRecieve                   :ARRAY[1..Range] OF WORD;
    scInternalCtrl:             STRUCT                                  
                                    b8:     BOOL:= FALSE;
                                    b9:     BOOL:= FALSE;
                                    b10:    BOOL:= FALSE;
                                    b11:    BOOL:= FALSE;
                                    b12:    BOOL:= FALSE;
                                    b13:    BOOL:= FALSE;
                                    b14:    BOOL:= FALSE;
                                    b15:    BOOL:= FALSE;
                                    b0:     BOOL:= FALSE;
                                    b1:     BOOL:= FALSE;
                                    b2:     BOOL:= FALSE;
                                    b3:     BOOL:= FALSE;
                                    b4:     BOOL:= FALSE;
                                    b5:     BOOL:= FALSE;
                                    b6:     BOOL:= FALSE;
                                    b7:     BOOL:= FALSE;
                                    awInt:  ARRAY[2..Range] OF WORD;
                                END_STRUCT;
                            
    scInternalState:            STRUCT                                  
                                    awInt:  ARRAY[1..Range] OF WORD;
                                END_STRUCT;

    wCtrl_IC                    :WORD:=0;
    xwCtrl_IC AT wCTRL_IC:       ARRAY[0..15] OF BOOL;
    
    iIn2_IC                     :INT:=0;
    iIn3_IC                     :INT:=0;
    iIn4_IC                     :INT:=0;
    iIn5_IC                     :INT:=0;
    iIn6_IC                     :INT:=0;
    iIn7_IC                     :INT:=0;
    iIn8_IC                     :INT:=0;
END_VAR

BEGIN

wFirstPeripherieADR:= INT_TO_WORD(iFirstPeripherieADR);             
iReadError:=0;
iWriteerror:=0;



IF xEnableInternalControl THEN                                    
   xInternalControlActive:=True;    
                           
ELSE 
   xInternalControlActive:=False;
   wCtrl_IC   := wCtrl;  
   iIn2_IC    := iIn2;                                                                  // Steuerung des Reglers über Eingangsvariablen des Bausteins
   iIn3_IC    := iIn3;                                                                  // Steuerung des Reglers über Eingangsvariablen des Bausteins
   iIn4_IC    := iIn4;                                                                   
   iIn5_IC    := iIn5;                                                                   
   iIn6_IC    := iIn6;                                                                   
   iIn7_IC    := iIn7;                                                                   
   iIn8_IC    := iIn8;  
   scInternalCtrl.b8 := xwCtrl_IC[8];
   scInternalCtrl.b9 := xwCtrl_IC[9];
   scInternalCtrl.b10 := xwCtrl_IC[10];
   scInternalCtrl.b11 := xwCtrl_IC[11];
   scInternalCtrl.b12 := xwCtrl_IC[12];
   scInternalCtrl.b13 := xwCtrl_IC[13];
   scInternalCtrl.b14 := xwCtrl_IC[14];
   scInternalCtrl.b15 := xwCtrl_IC[15];
   scInternalCtrl.b0 := xwCtrl_IC[0];
   scInternalCtrl.b1 := xwCtrl_IC[1];
   scInternalCtrl.b2 := xwCtrl_IC[2];
   scInternalCtrl.b3 := xwCtrl_IC[3];
   scInternalCtrl.b4 := xwCtrl_IC[4];
   scInternalCtrl.b5 := xwCtrl_IC[5];
   scInternalCtrl.b6 := xwCtrl_IC[6];
   scInternalCtrl.b7 := xwCtrl_IC[7];
                                                                 
END_IF;
           
iReadError:= DPRD_DAT(
                        LADDR := wFirstPeripherieADR, 
                        RECORD := scInternalState ); 
                        
// Prozessdaten auf die Ausgänge kopieren
    wState  := scInternalState.awInt[1];
    iOut2   := WORD_TO_INT(scInternalState.awInt[2]);
    iOut3   := WORD_TO_INT(scInternalState.awInt[3]);
    iOut4   := WORD_TO_INT(scInternalState.awInt[4]);
    iOut5   := WORD_TO_INT(scInternalState.awInt[5]);
    iOut6   := WORD_TO_INT(scInternalState.awInt[6]);
    iOut7   := WORD_TO_INT(scInternalState.awInt[7]);
    iOut8   := WORD_TO_INT(scInternalState.awInt[8]);
    
// Schreiben der Eingänge auf die Prozessdaten
    
    scInternalCtrl.awInt[2]   :=INT_TO_WORD(iIn2_IC);
    scInternalCtrl.awInt[3]   :=INT_TO_WORD(iIn3_IC);
    scInternalCtrl.awInt[4]   :=INT_TO_WORD(iIn4_IC);
    scInternalCtrl.awInt[5]   :=INT_TO_WORD(iIn5_IC);
    scInternalCtrl.awInt[6]   :=INT_TO_WORD(iIn6_IC);
    scInternalCtrl.awInt[7]   :=INT_TO_WORD(iIn7_IC);
    scInternalCtrl.awInt[8]   :=INT_TO_WORD(iIn8_IC);
   
                        
iWriteError:=DPWR_DAT(
                        LADDR := wFirstPeripherieADR, 
                        RECORD := scInternalCtrl ); 
                        
                                                                    // Setzen der Stausvariablen
IF (iReadError <> 0) OR (iWriteError <> 0) THEN
    xError:= true;
    xCommunicationOK:=false;
ELSE
    xError:= false;
    xCommunicationOK:=True;
END_IF;
     
END_FUNCTION_BLOCK